use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{Instruction, BytecodeReader, self}, rtda::{heap, Frame}};


#[derive(Debug, Default)]
pub struct INVOKE_SPECIAL {
    index: usize, //被调用的方法的符号引用（CONSTANT_Methodref_info或者CONSTANT_InterfaceMethodref_info常量）
}

impl Instruction for INVOKE_SPECIAL {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u16() as usize;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let method = frame.borrow().get_method();
        let method_ref = method;
        let current_class = method_ref.get_class();
        let cp = current_class.get_constant_pool().unwrap();
        let method_ref = cp.get_constant(self.index).unwrap().method_ref();
        let mut mr_mut = method_ref.lock().unwrap();
        let resolved_class = mr_mut.resolved_class();
        let rcr =  &*resolved_class;
        let resolved_method = mr_mut.resolved_method();

        if resolved_method.get_name() == "<init>" 
        && !std::ptr::eq(resolved_method.get_class().as_ref(), rcr) {
            panic!("java.lang.NoSushMethodError");
        }
        // 静态方法，抛出异常
        if resolved_method.is_static() {
            panic!("java.lang.IncompatibleClassChangeError")
        }
        // 获取this引用   stack: n n this x x x x; x为参数代表4个。 实例方法会在第五个位置加上this引用
        let _ref = frame.borrow().get_operand_stack().borrow().get_ref_from_top(resolved_method.get_arg_slot_count() - 1);
        if _ref.is_none() {
            panic!("java.lang.NullPointerException");
        }
        let _ref = _ref.unwrap();
        let arc_class = unsafe { &*_ref }.get_class();
        let ref_class =  &*arc_class;
        // 确保protected方法只能被声明该方法的类或子类调用
        if resolved_method.is_protected() 
        && resolved_method.get_class().is_sub_class_of(current_class.as_ref())
        && resolved_method.get_class().get_package_name() != current_class.get_package_name()
        && !std::ptr::eq(ref_class, current_class.as_ref())
        && !ref_class.is_sub_class_of(current_class.as_ref()) {
            panic!("java.lang.IllegalAccessError")
        }
        // 当前类被ACC_SUPER标志 调用父类中的非构造方法 需要从方法符号引用中解析出需要调用的方法
        let mut method_to_be_invoked = Some(resolved_method.clone());
        if current_class.is_super()
        && rcr.is_sub_class_of(current_class.as_ref())
        && resolved_method.get_name() != "<init>" {
            method_to_be_invoked = heap::lookup_method_in_class(current_class, mr_mut.get_name(), mr_mut.get_descriptor());
        }
        // 未查找到或方法是抽象的抛出异常
        if method_to_be_invoked.is_none() || method_to_be_invoked.as_ref().unwrap().is_abstract() {
            panic!("java.lang.AbstractMethodError");
        }

        base::invoke_method(frame, method_to_be_invoked.unwrap());

    }


}
